/* lib
 ************************************************
 * Object-MD
 * Object Oriented Molecular Dynamics Program
 * 
 * (c)Yudi Rosandi, 2005
 *
 * Version 0.1 (05.2006)
 *
 * Project started on July 2005.
 *
 ************************************************
 * Object-MD Header file
 *
 * Configuration file reader
 *
*/

#ifndef _CFG_READER_H_
#define _CFG_READER_H_

#include <fstream>
#include <vector>
#include <string>
#include <sstream>

using std::vector;
using std::string;
using std::istringstream;
/*
	Eratum:  
		- << operator in the same line will fail while using
		  string functions, because it uses the same string buffer.
*/

//!Configuration file reader
/**
 * ConfigReader class is an independent class which has duty to
 * read all the tokens from the configuration file. The file consist of
 * 'tag' and 'value' tokens, writen in the following format:
 *
 * tag = value
 * 
 * Value can be one of three types, double (decimal number), integer (number), 
 * boolean (true or false), or a three number vector (see GetVector()).
 *
 * The tag and the corresponding value are stored in the c++ vector-list form.
 * User can access the value by refferencing the tag name with help of
 * four member functions: GetDouble(), GetInt(), GetVector(), and GetBool().
 *
*/

class ConfigReader {
protected:
	char ConfigFile[128];
	vector<string> Tag;
	vector<string> Value;
	istringstream CfgStream;

public:
	ConfigReader(){ConfigFile[0]='\0';}
	ConfigReader(const string cfg_fl, bool extract=false, const char* magicword=NULL);
	~ConfigReader();
	
	static char*  TagMember(const char* tag, const char* member);
	
	// first member is 1, member=0 means tag without member
	static char*  TagMember(const char* tag, const int member);
	
	void   ReadFile(const string cfg_fl, bool setname=true);
	bool   ExtractFile(const string txt_file, const char* magicword=NULL);
	
	virtual void   Read(const string cfg_fl){ReadFile(cfg_fl,true);}

	// FIXME! how to overwrite values upon reading in this function???
	virtual void   Append(const string app_cfg,bool overwrite=false)
	               { /*.....to append a configuration file....*/}
	
	virtual void   Extract(const string txt_file, const char* magicword=NULL)
				   {ExtractFile(txt_file,magicword);}
				   
	void           PushPair(string tag, string val);
	
	virtual bool   Exist(const char* tag);
	virtual bool   ExistMember(const char* tag, const int member){return Exist(TagMember(tag, member));}
	virtual bool   ExistMember(const char* tag, const char* member){return Exist(TagMember(tag, member));}

	virtual double GetDouble(const char* tag);
	virtual bool   GetBool(const char* tag);
	virtual int    GetInt(const char* tag);
	virtual istringstream& GetStringStream(const char* tag=NULL);
	virtual char*  GetString(const char* tag);
	virtual char*  GetString(const char* tag, char* streturn);
	virtual char*  GetStringLast(const char* tag, const int startpos);
	virtual char*  GetStringLast(const char* tag, const int startpos, char* streturn);
	virtual double GetVector(const char* tag, const int elem);
	virtual void   GetVector(const char* tag, double &x, double &y, double &z);
	virtual char*  GetWord(const char* tag, const int wordpos);
	virtual char*  GetWord(const char* tag, const int wordpos, char* streturn);
	
	virtual int  GetVectorSize(const char* tag);
	virtual int  GetMemberSize(const char* tag);
	
	virtual double* GetVectorDouble(const char* tag, int &len);
	virtual int*    GetVectorInt(const char* tag, int &len);

	
	virtual void   Set(const char* tag, const double value);
	virtual void   Set(const char* tag, const int value);
	virtual void   Set(const char* tag, const bool value);
	virtual void   Set(const char* tag, const char* value);
	
	virtual void Dump(const char* fname);
	virtual void ErrorHandler(void* errstuff){}
	
	virtual char* GetFilename() {return ConfigFile;}
	// Static members
	static void Trim(string& vst);
	
	// new functions...
	virtual string  PeekString(const string tag){
		if(Exist(tag.c_str())) return GetString(tag.c_str());
		return "";
	}
};

#endif
